package com.datagateway.component;

import com.datagateway.model.ProcessedData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 数据源管理器
 * 支持多种数据源的统一管理和操作
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class DataSourceManager {

    private static final Logger logger = LoggerFactory.getLogger(DataSourceManager.class);

    @Autowired
    private AlertManager alertManager;

    @Autowired
    private SystemMonitor systemMonitor;

    // 数据源实例映射
    private final Map<String, DataSourceInstance> dataSources = new ConcurrentHashMap<>();
    
    // 数据源统计信息
    private final Map<String, DataSourceStatistics> statistics = new ConcurrentHashMap<>();
    
    // 线程池
    private ExecutorService executorService;
    
    // 配置信息
    private boolean enabled = true;
    private int maxConnections = 100;
    private long connectionTimeout = 30000;
    private long queryTimeout = 60000;
    private int batchSize = 1000;
    private boolean autoCommit = true;
    private boolean poolingEnabled = true;
    private int poolSize = 10;
    private long poolTimeout = 30000;

    @PostConstruct
    public void initialize() {
        logger.info("初始化数据源管理器...");
        
        // 初始化线程池
        executorService = Executors.newFixedThreadPool(10);
        
        // 初始化默认数据源
        initializeDefaultDataSources();
        
        logger.info("数据源管理器初始化完成，支持的数据源类型: {}", getSupportedDataSourceTypes());
    }

    @PreDestroy
    public void destroy() {
        logger.info("销毁数据源管理器...");
        
        // 关闭所有数据源连接
        closeAllDataSources();
        
        // 关闭线程池
        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown();
        }
        
        logger.info("数据源管理器销毁完成");
    }

    /**
     * 初始化默认数据源
     */
    private void initializeDefaultDataSources() {
        // 这里可以初始化一些默认的数据源配置
        logger.info("初始化默认数据源配置");
    }

    /**
     * 获取支持的数据源类型
     */
    public List<String> getSupportedDataSourceTypes() {
        return Arrays.asList(
            "MYSQL", "POSTGRESQL", "MONGODB", "REDIS", 
            "ELASTICSEARCH", "HIVE", "ORACLE", "SQLSERVER"
        );
    }

    /**
     * 创建数据源
     */
    public boolean createDataSource(String name, String type, Map<String, Object> config) {
        try {
            logger.info("创建数据源: name={}, type={}", name, type);
            
            // 验证数据源类型
            if (!getSupportedDataSourceTypes().contains(type.toUpperCase())) {
                logger.error("不支持的数据源类型: {}", type);
                return false;
            }
            
            // 创建数据源实例
            DataSourceInstance instance = createDataSourceInstance(type, config);
            if (instance == null) {
                logger.error("创建数据源实例失败: {}", name);
                return false;
            }
            
            // 测试连接
            if (!instance.testConnection()) {
                logger.error("数据源连接测试失败: {}", name);
                return false;
            }
            
            // 添加到管理器
            dataSources.put(name, instance);
            statistics.put(name, new DataSourceStatistics());
            
            logger.info("数据源创建成功: {}", name);
            return true;
            
        } catch (Exception e) {
            logger.error("创建数据源失败: name={}, error={}", name, e.getMessage(), e);
            alertManager.sendSystemErrorAlert("数据源创建失败", e.getMessage());
            return false;
        }
    }

    /**
     * 创建数据源实例
     */
    private DataSourceInstance createDataSourceInstance(String type, Map<String, Object> config) {
        try {
            switch (type.toUpperCase()) {
                case "MYSQL":
                    return new MySQLDataSource(config);
                case "POSTGRESQL":
                    return new PostgreSQLDataSource(config);
                case "MONGODB":
                    return new MongoDBDataSource(config);
                case "REDIS":
                    return new RedisDataSource(config);
                case "ELASTICSEARCH":
                    return new ElasticsearchDataSource(config);
                case "HIVE":
                    return new HiveDataSource(config);
                default:
                    logger.error("不支持的数据源类型: {}", type);
                    return null;
            }
        } catch (Exception e) {
            logger.error("创建数据源实例失败: type={}, error={}", type, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 删除数据源
     */
    public boolean removeDataSource(String name) {
        try {
            logger.info("删除数据源: {}", name);
            
            DataSourceInstance instance = dataSources.remove(name);
            if (instance != null) {
                instance.close();
                statistics.remove(name);
                logger.info("数据源删除成功: {}", name);
                return true;
            } else {
                logger.warn("数据源不存在: {}", name);
                return false;
            }
            
        } catch (Exception e) {
            logger.error("删除数据源失败: name={}, error={}", name, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 获取数据源
     */
    public DataSourceInstance getDataSource(String name) {
        return dataSources.get(name);
    }

    /**
     * 获取所有数据源
     */
    public Map<String, DataSourceInstance> getAllDataSources() {
        return new HashMap<>(dataSources);
    }

    /**
     * 测试数据源连接
     */
    public boolean testConnection(String name) {
        DataSourceInstance instance = dataSources.get(name);
        if (instance == null) {
            logger.error("数据源不存在: {}", name);
            return false;
        }
        
        try {
            boolean result = instance.testConnection();
            if (result) {
                logger.info("数据源连接测试成功: {}", name);
            } else {
                logger.error("数据源连接测试失败: {}", name);
            }
            return result;
        } catch (Exception e) {
            logger.error("数据源连接测试异常: name={}, error={}", name, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 写入数据到指定数据源
     */
    public boolean writeData(String dataSourceName, List<ProcessedData> dataList) {
        DataSourceInstance instance = dataSources.get(dataSourceName);
        if (instance == null) {
            logger.error("数据源不存在: {}", dataSourceName);
            return false;
        }
        
        try {
            long startTime = System.currentTimeMillis();
            boolean result = instance.writeData(dataList);
            long endTime = System.currentTimeMillis();
            
            // 更新统计信息
            DataSourceStatistics stats = statistics.get(dataSourceName);
            if (stats != null) {
                stats.recordWrite(dataList.size(), endTime - startTime, result);
            }
            
            if (result) {
                logger.info("数据写入成功: dataSource={}, count={}, time={}ms", 
                    dataSourceName, dataList.size(), endTime - startTime);
            } else {
                logger.error("数据写入失败: dataSource={}, count={}", dataSourceName, dataList.size());
            }
            
            return result;
            
        } catch (Exception e) {
            logger.error("数据写入异常: dataSource={}, error={}", dataSourceName, e.getMessage(), e);
            alertManager.sendSystemErrorAlert("数据写入失败", e.getMessage());
            return false;
        }
    }

    /**
     * 从指定数据源读取数据
     */
    public List<ProcessedData> readData(String dataSourceName, String query, Map<String, Object> parameters) {
        DataSourceInstance instance = dataSources.get(dataSourceName);
        if (instance == null) {
            logger.error("数据源不存在: {}", dataSourceName);
            return Collections.emptyList();
        }
        
        try {
            long startTime = System.currentTimeMillis();
            List<ProcessedData> result = instance.readData(query, parameters);
            long endTime = System.currentTimeMillis();
            
            // 更新统计信息
            DataSourceStatistics stats = statistics.get(dataSourceName);
            if (stats != null) {
                stats.recordRead(result.size(), endTime - startTime, true);
            }
            
            logger.info("数据读取成功: dataSource={}, count={}, time={}ms", 
                dataSourceName, result.size(), endTime - startTime);
            
            return result;
            
        } catch (Exception e) {
            logger.error("数据读取异常: dataSource={}, error={}", dataSourceName, e.getMessage(), e);
            alertManager.sendSystemErrorAlert("数据读取失败", e.getMessage());
            return Collections.emptyList();
        }
    }

    /**
     * 执行SQL语句
     */
    public boolean executeSql(String dataSourceName, String sql, Map<String, Object> parameters) {
        DataSourceInstance instance = dataSources.get(dataSourceName);
        if (instance == null) {
            logger.error("数据源不存在: {}", dataSourceName);
            return false;
        }
        
        try {
            long startTime = System.currentTimeMillis();
            boolean result = instance.executeSql(sql, parameters);
            long endTime = System.currentTimeMillis();
            
            // 更新统计信息
            DataSourceStatistics stats = statistics.get(dataSourceName);
            if (stats != null) {
                stats.recordExecute(endTime - startTime, result);
            }
            
            if (result) {
                logger.info("SQL执行成功: dataSource={}, time={}ms", dataSourceName, endTime - startTime);
            } else {
                logger.error("SQL执行失败: dataSource={}", dataSourceName);
            }
            
            return result;
            
        } catch (Exception e) {
            logger.error("SQL执行异常: dataSource={}, error={}", dataSourceName, e.getMessage(), e);
            alertManager.sendSystemErrorAlert("SQL执行失败", e.getMessage());
            return false;
        }
    }

    /**
     * 关闭所有数据源
     */
    public void closeAllDataSources() {
        logger.info("关闭所有数据源连接...");
        
        for (Map.Entry<String, DataSourceInstance> entry : dataSources.entrySet()) {
            try {
                entry.getValue().close();
                logger.info("数据源连接已关闭: {}", entry.getKey());
            } catch (Exception e) {
                logger.error("关闭数据源连接失败: name={}, error={}", entry.getKey(), e.getMessage(), e);
            }
        }
        
        dataSources.clear();
        statistics.clear();
    }

    /**
     * 获取数据源统计信息
     */
    public DataSourceStatistics getStatistics(String dataSourceName) {
        return statistics.get(dataSourceName);
    }

    /**
     * 获取所有数据源统计信息
     */
    public Map<String, DataSourceStatistics> getAllStatistics() {
        return new HashMap<>(statistics);
    }

    /**
     * 获取管理器统计信息
     */
    public ManagerStatistics getManagerStatistics() {
        ManagerStatistics stats = new ManagerStatistics();
        stats.setTotalDataSources(dataSources.size());
        stats.setEnabledDataSources((int) dataSources.values().stream()
            .filter(DataSourceInstance::isConnected).count());
        stats.setTotalOperations(statistics.values().stream()
            .mapToLong(DataSourceStatistics::getTotalOperations).sum());
        stats.setSuccessfulOperations(statistics.values().stream()
            .mapToLong(DataSourceStatistics::getSuccessfulOperations).sum());
        stats.setFailedOperations(statistics.values().stream()
            .mapToLong(DataSourceStatistics::getFailedOperations).sum());
        stats.setAverageResponseTime(statistics.values().stream()
            .mapToDouble(DataSourceStatistics::getAverageResponseTime).average().orElse(0.0));
        stats.setLastUpdateTime(System.currentTimeMillis());
        
        return stats;
    }

    /**
     * 设置配置
     */
    public void setConfiguration(boolean enabled, int maxConnections, long connectionTimeout, 
                                long queryTimeout, int batchSize, boolean autoCommit, 
                                boolean poolingEnabled, int poolSize, long poolTimeout) {
        this.enabled = enabled;
        this.maxConnections = maxConnections;
        this.connectionTimeout = connectionTimeout;
        this.queryTimeout = queryTimeout;
        this.batchSize = batchSize;
        this.autoCommit = autoCommit;
        this.poolingEnabled = poolingEnabled;
        this.poolSize = poolSize;
        this.poolTimeout = poolTimeout;
        
        logger.info("数据源管理器配置已更新");
    }

    // Getters and Setters
    public boolean isEnabled() { return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }
    public int getMaxConnections() { return maxConnections; }
    public void setMaxConnections(int maxConnections) { this.maxConnections = maxConnections; }
    public long getConnectionTimeout() { return connectionTimeout; }
    public void setConnectionTimeout(long connectionTimeout) { this.connectionTimeout = connectionTimeout; }
    public long getQueryTimeout() { return queryTimeout; }
    public void setQueryTimeout(long queryTimeout) { this.queryTimeout = queryTimeout; }
    public int getBatchSize() { return batchSize; }
    public void setBatchSize(int batchSize) { this.batchSize = batchSize; }
    public boolean isAutoCommit() { return autoCommit; }
    public void setAutoCommit(boolean autoCommit) { this.autoCommit = autoCommit; }
    public boolean isPoolingEnabled() { return poolingEnabled; }
    public void setPoolingEnabled(boolean poolingEnabled) { this.poolingEnabled = poolingEnabled; }
    public int getPoolSize() { return poolSize; }
    public void setPoolSize(int poolSize) { this.poolSize = poolSize; }
    public long getPoolTimeout() { return poolTimeout; }
    public void setPoolTimeout(long poolTimeout) { this.poolTimeout = poolTimeout; }

    /**
     * 数据源实例接口
     */
    public interface DataSourceInstance {
        boolean testConnection();
        boolean writeData(List<ProcessedData> dataList);
        List<ProcessedData> readData(String query, Map<String, Object> parameters);
        boolean executeSql(String sql, Map<String, Object> parameters);
        boolean isConnected();
        void close();
        String getType();
        Map<String, Object> getConfig();
    }

    /**
     * 数据源统计信息
     */
    public static class DataSourceStatistics {
        private final AtomicLong totalOperations = new AtomicLong(0);
        private final AtomicLong successfulOperations = new AtomicLong(0);
        private final AtomicLong failedOperations = new AtomicLong(0);
        private final AtomicLong totalResponseTime = new AtomicLong(0);
        private final AtomicLong totalRecords = new AtomicLong(0);
        private long lastOperationTime = 0;
        private long createTime = System.currentTimeMillis();

        public void recordWrite(int recordCount, long responseTime, boolean success) {
            totalOperations.incrementAndGet();
            totalResponseTime.addAndGet(responseTime);
            totalRecords.addAndGet(recordCount);
            lastOperationTime = System.currentTimeMillis();
            
            if (success) {
                successfulOperations.incrementAndGet();
            } else {
                failedOperations.incrementAndGet();
            }
        }

        public void recordRead(int recordCount, long responseTime, boolean success) {
            totalOperations.incrementAndGet();
            totalResponseTime.addAndGet(responseTime);
            totalRecords.addAndGet(recordCount);
            lastOperationTime = System.currentTimeMillis();
            
            if (success) {
                successfulOperations.incrementAndGet();
            } else {
                failedOperations.incrementAndGet();
            }
        }

        public void recordExecute(long responseTime, boolean success) {
            totalOperations.incrementAndGet();
            totalResponseTime.addAndGet(responseTime);
            lastOperationTime = System.currentTimeMillis();
            
            if (success) {
                successfulOperations.incrementAndGet();
            } else {
                failedOperations.incrementAndGet();
            }
        }

        // Getters
        public long getTotalOperations() { return totalOperations.get(); }
        public long getSuccessfulOperations() { return successfulOperations.get(); }
        public long getFailedOperations() { return failedOperations.get(); }
        public long getTotalResponseTime() { return totalResponseTime.get(); }
        public long getTotalRecords() { return totalRecords.get(); }
        public long getLastOperationTime() { return lastOperationTime; }
        public long getCreateTime() { return createTime; }
        public double getSuccessRate() { 
            long total = totalOperations.get();
            return total > 0 ? (double) successfulOperations.get() / total : 0.0;
        }
        public double getAverageResponseTime() {
            long total = totalOperations.get();
            return total > 0 ? (double) totalResponseTime.get() / total : 0.0;
        }
    }

    /**
     * 管理器统计信息
     */
    public static class ManagerStatistics {
        private int totalDataSources;
        private int enabledDataSources;
        private long totalOperations;
        private long successfulOperations;
        private long failedOperations;
        private double averageResponseTime;
        private long lastUpdateTime;

        // Getters and Setters
        public int getTotalDataSources() { return totalDataSources; }
        public void setTotalDataSources(int totalDataSources) { this.totalDataSources = totalDataSources; }
        public int getEnabledDataSources() { return enabledDataSources; }
        public void setEnabledDataSources(int enabledDataSources) { this.enabledDataSources = enabledDataSources; }
        public long getTotalOperations() { return totalOperations; }
        public void setTotalOperations(long totalOperations) { this.totalOperations = totalOperations; }
        public long getSuccessfulOperations() { return successfulOperations; }
        public void setSuccessfulOperations(long successfulOperations) { this.successfulOperations = successfulOperations; }
        public long getFailedOperations() { return failedOperations; }
        public void setFailedOperations(long failedOperations) { this.failedOperations = failedOperations; }
        public double getAverageResponseTime() { return averageResponseTime; }
        public void setAverageResponseTime(double averageResponseTime) { this.averageResponseTime = averageResponseTime; }
        public long getLastUpdateTime() { return lastUpdateTime; }
        public void setLastUpdateTime(long lastUpdateTime) { this.lastUpdateTime = lastUpdateTime; }
        public double getSuccessRate() {
            return totalOperations > 0 ? (double) successfulOperations / totalOperations : 0.0;
        }
    }
}
